package com.bys.system.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bys.constant.CrmSystemConstant;
import com.bys.constant.HttpContant;
import com.bys.exception.BysOaSystemException;
import com.bys.response.Result;
import com.bys.security.CrmGrantedAuthority;
import com.bys.security.CrmUser;
import com.bys.system.model.SysRoleModel;
import com.bys.system.model.SysUserModel;
import com.bys.system.model.SysUserRoleModel;
import com.bys.system.service.ISysMenuService;
import com.bys.system.service.ISysRoleService;
import com.bys.system.service.ISysUserRoleService;
import com.bys.system.service.ISysUserService;
import com.bys.system.service.impl.MailService;
import com.bys.system.vo.*;
import com.bys.util.JwtUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户表 前端控制器
 * </p>
 *
 * @author bys
 * @since 2023-03-31
 */
@Slf4j
@Api(tags = "用户接口")
@RestController
@Validated
@RequestMapping("/system/sysUser")
public class SysUserController {
    @Resource
    private ISysMenuService sysMenuService;
    @Resource
    private ISysUserService sysUserService;
    @Resource
    private ISysRoleService roleService;
    @Resource
    private ISysUserRoleService sysUserRoleService;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private MailService mailService;

    @ApiOperation(value = "用户 注册", notes = "需要 username,password,email")
    @PostMapping("/signup")
    @Transactional(rollbackFor = Exception.class)
    public Result register(@RequestBody @Valid CreateUserVo userVo) {
        SysUserModel userModel = sysUserService.getOne(Wrappers.lambdaQuery(SysUserModel.class)
                .eq(SysUserModel::getUsername, userVo.getUsername()).eq(SysUserModel::getIsDeleted, Boolean.FALSE).or().eq(SysUserModel::getEmail, userVo.getEmail()));
        if (userModel != null) {
            throw new BysOaSystemException("该账号已注册，请重新填写账号或邮箱");
        }
        SysUserModel sysUserModel = new SysUserModel();
        sysUserModel.setUsername(userVo.getUsername());
        String encodePassword = new BCryptPasswordEncoder().encode(userVo.getPassword());
        sysUserModel.setPassword(encodePassword);
        sysUserModel.setEmail(userVo.getEmail());
        sysUserModel.setStatus(CrmSystemConstant.ENABLE_STATUS);
        sysUserModel.setIsDeleted(Boolean.FALSE);
        SysUserRoleModel userRoleModel = new SysUserRoleModel();
        sysUserService.save(sysUserModel);
        userRoleModel.setUserId(sysUserModel.getId());
        userRoleModel.setRoleId(CrmSystemConstant.user_RoleId);
        sysUserRoleService.save(userRoleModel);
        return Result.success();
    }

    @ApiOperation(value = "使用id 查询用户信息", notes = " 参数 id")
    @GetMapping("/{id}")
    public Result getById(@PathVariable Long id) {
        SysUserModel sysUserModel = sysUserService.getById(id);
        Optional.ofNullable(sysUserModel).orElseThrow(() -> new BysOaSystemException("该用户不存在"));
        SysUserInfoVo sysUserInfoVo = new SysUserInfoVo();
        BeanUtil.copyProperties(sysUserModel, sysUserInfoVo);
        if(Objects.nonNull(sysUserModel.getDeptId())){
            sysUserInfoVo.setDeptName(sysUserModel.getDeptId().toString());
        }
        List<SysRoleModel> userRoleModels = sysUserRoleService.getRole(sysUserModel.getId());
        sysUserInfoVo.setOfRole(userRoleModels.stream().map(SysRoleModel::getId).collect(Collectors.toList()));
        return Result.success(sysUserInfoVo);
    }

    @ApiOperation(value = "保存用户信息", notes = "参数 sysUserModel ")
    @PostMapping("/save")
    public Result save(@RequestBody CreateUserVo createUserVo) {
        sysUserService.saveUser(createUserVo);
        return Result.success();
    }

    @ApiOperation(value = "修改用户信息", notes = "参数 sysUserModel")
    @PutMapping("/update")
    @Transactional(rollbackFor = Exception.class)
    public Result update(@RequestBody UpdateUserVo updateUserVo) {
        SysUserModel sysUserModel = new SysUserModel();
        BeanUtil.copyProperties(updateUserVo, sysUserModel);
        sysUserModel.setUpdateTime(LocalDateTime.now());
        sysUserService.updateById(sysUserModel);
        // 先将所有用户的 所属角色删除
        sysUserRoleService.remove(Wrappers.lambdaQuery(SysUserRoleModel.class).eq(SysUserRoleModel::getUserId, sysUserModel.getId()));
        // 修改 用户所属角色
        updateUserVo.getOfRole().forEach(roleId -> {
            SysRoleModel roleModel = roleService.getById(roleId);
            if (roleModel == null || roleModel.getIsDeleted()) {
                throw new BysOaSystemException("用户所属角色不存在");
            }
            SysUserRoleModel sysUserRoleModel = new SysUserRoleModel();
            sysUserRoleModel.setRoleId(roleModel.getId());
            sysUserRoleModel.setUserId(sysUserModel.getId());
            sysUserRoleService.save(sysUserRoleModel);
        });
        return Result.success();
    }

    @ApiOperation(value = "删除用户", notes = "参数 ： id")
    @DeleteMapping("/delete/{id}")
    public Result delete(@PathVariable Long id) {
        sysUserService.deleteLogic(id);
        return Result.success();
    }

    @ApiOperation(value = "批量删除", notes = "ids 集合")
    @DeleteMapping("/deleteBatch")
    @Transactional(rollbackFor = Exception.class)
    public Result deleteBatch(@RequestBody List<Long> ids) {
        ids.forEach(id -> {
            sysUserService.deleteLogic(id);
        });
        return Result.success();
    }

    @ApiOperation(value = "修改用户账号是否可用", notes = "id:用户id, status： 1 可用")
    @GetMapping("/status/{id}/{status}")
    @Transactional(rollbackFor = Exception.class)
    public Result updateStatus(@PathVariable Long id, @PathVariable Integer status) {
        SysUserModel sysUserModel = new SysUserModel();
        sysUserModel.setId(id);
        if (status != null && status == 1) {
            sysUserModel.setStatus(status);
        } else {
            sysUserModel.setStatus(CrmSystemConstant.Zero);
        }
        sysUserService.updateById(sysUserModel);
        return Result.success();
    }

    @ApiOperation(value = "分页查询 用户", notes = "pageNo 当前页 pageSize 每页大小 sysUserModel 查询对象")
    @GetMapping("/getPageList/{pageNo}/{pageSize}")
    public Result getPageList(@PathVariable Integer pageNo, @PathVariable Integer pageSize, SysUserVo sysUserVo) {
        Page<SysUserVo> data = sysUserService.getUserPage(pageNo, pageSize, sysUserVo);
        Optional.ofNullable(data).orElseThrow(() -> new BysOaSystemException("用户列表不存在"));
        return Result.success(data);
    }

    @ApiOperation(value = "发送验证码", notes = "email 发送")
    @GetMapping("/sendCode/{email}")
    public Result checkCode(@PathVariable String email) {
        if (StringUtils.isNotBlank(stringRedisTemplate.opsForValue().get(email))) {
            throw new BysOaSystemException("验证码在有效期内，请稍后再试");
        }
        String code = RandomUtil.randomNumbers(6);
        stringRedisTemplate.opsForValue().set(email, code, 60, TimeUnit.SECONDS);
        mailService.sendMail(email, "验证码", String.format(CrmSystemConstant.codeMessage, code));
        return Result.success();
    }

    @ApiOperation(value = "用户登录", notes = "参数 username,password")
    @PostMapping("/code/login")
    public Result login(@RequestBody LoginUserVo loginUserVo) throws JsonProcessingException {
        if (StringUtils.isBlank(loginUserVo.getUsername()) && StringUtils.isBlank(loginUserVo.getPassword())) {
            String code = stringRedisTemplate.opsForValue().get(loginUserVo.getEmail());
            if (StringUtils.isBlank(code) || !code.equals(loginUserVo.getCode())) {
                throw new BysOaSystemException("验证码不可用");
            }
        }
        String email = loginUserVo.getEmail();
        SysUserModel sysUser = sysUserService.getOne(Wrappers.lambdaQuery(SysUserModel.class)
                .eq(SysUserModel::getEmail, email).eq(SysUserModel::getIsDeleted, Boolean.FALSE));

        Optional.ofNullable(sysUser).orElseThrow(() -> new BysOaSystemException(403, "用户不存在"));
        if (CrmSystemConstant.Zero.equals(sysUser.getStatus())) {
            throw new BysOaSystemException(HttpContant.NO_PERMISSION, "账号已停用！！");
        }
        String token = JwtUtil.createToken(sysUser.getId(), sysUser.getUsername());
        List<String> permissions = sysMenuService.findUserPermission(sysUser.getId());
        // 添加权限
        Set<CrmGrantedAuthority> auths = new HashSet<>();
        permissions.forEach( p ->{
            auths.add(new CrmGrantedAuthority(p));
        });
        stringRedisTemplate.opsForValue().set(token,new ObjectMapper().writeValueAsString(auths));
        HashMap<String, String> map = new HashMap<>();
        map.put("token", token);
        return Result.success(map);
    }

    @ApiOperation(value = "获取用户信息", notes = "参数 token")
    @GetMapping("/info")
    public Result getUserInfo() {
        Long userId = LoginUserHelper.getUserId();
        UserInfoVo userInfoVo = sysUserService.getUserInfo(userId);
        return Result.success(userInfoVo);
    }

    @ApiOperation(value = "用户 退出", notes = "没有参数")
    @PostMapping("/logout")
    public Result logout() {
        return Result.success();
    }


}
